﻿using System;
using System.Collections.Generic;
using UnityEngine;

public class ElementSwirlState : IElementState
{
    private class Item
    {
        /// <summary>
        /// 扩散类型
        /// </summary>
        public ElementType ElementType { get; set; }

        /// <summary>
        /// 扩散元素量
        /// </summary>
        public float Gauge { get; set; }
    }

    private const float Radius = 10f;

    private readonly Collider[] _cache = new Collider[99];
    private readonly List<Item> _items = new();

    /// <summary>
    /// 附加源
    /// </summary>
    public GameObject Source { get; set; }

    /// <summary>
    /// 是否已启动
    /// </summary>
    public bool IsStarted { get; private set; }

    public void Start(GameObject source)
    {
        Source = source;
        IsStarted = true;
    }

    public void Stop()
    {
        IsStarted = false;
    }

    public void Update(float deltaTime)
    {
        if (_items.Count > 0)
        {
            Swirl();
            _items.Clear();
        }
    }

    private void Swirl()
    {
        // 造成范围伤害并附加元素
        foreach (var item in _items)
        {
            // 对自身造成扩散伤害
            TakeDamage(item);

            var count = Physics.OverlapSphereNonAlloc(Source.transform.position, Radius,
                _cache);
            for (int i = 0; i < count; i++)
            {
                SwirlDamage(_cache[i].gameObject, item);
            }
        }
    }


    /// <summary>
    /// 对自身造成扩散伤害
    /// </summary>
    /// <param name="item"></param>
    private void TakeDamage(Item item)
    {
        var attackData = new AttackData
        {
            Damage = 100f,
            Source = Source,
            ElementType = item.ElementType,
            ElementGauge = 0f,
            StrikeType = StrikeType.None
        };
        Source.GetComponent<ActorDamageable>().TakeDamage(attackData);
    }

    /// <summary>
    /// 造成扩散伤害
    /// </summary>
    /// <param name="other"></param>
    /// <param name="item"></param>
    private void SwirlDamage(GameObject other, Item item)
    {
        // 不对自身附着元素
        if (other.gameObject == Source)
        {
            return;
        }

        // 不是同一阵营
        if (!other.gameObject.CompareTag(Source.tag))
        {
            return;
        }

        if (other.TryGetComponent(out ActorDamageable damageable))
        {
            // todo: 每次扩散最多造成2次同属性伤害，必须知道详细机制，也许需要大改动
            var attackData = new AttackData
            {
                Damage = 100f,
                Source = Source,
                ElementType = item.ElementType,
                ElementGauge = item.Gauge,
                StrikeType = StrikeType.None
            };
            damageable.TakeDamage(attackData);
        }
    }

    /// <summary>
    /// 增加扩散
    /// </summary>
    /// <param name="elementType">元素类型</param>
    /// <param name="gauge">元素量</param>
    public void AddSwirl(ElementType elementType, float gauge)
    {
        foreach (var item in _items)
        {
            if (item.ElementType == elementType)
            {
                throw new ArgumentException("element already exists.", nameof(elementType));
            }
        }

        _items.Add(new Item
        {
            ElementType = elementType,
            Gauge = gauge
        });

        Debug.Log($"增加扩散元素：{elementType} | {gauge}");
    }
}